package com.ochnas.volunteersignup.domain;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

@Entity
public class Event implements Serializable {
	@Transient
	private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MMM.dd.yyyy");
	
	@Transient
	private static Comparator<Position> sortByAscendingName = new Comparator<Position>() {

		@Override
		public int compare(Position p1, Position p2) {
			String p1Name = p1.getName();
			String p2Name = p2.getName();
			return p1Name.compareTo(p2Name);
		}
		
	};
	
	
	@Id @GeneratedValue
	private Long id = null;
	@Column(name = "NAME", nullable = false)
	private String name;
	private String description;
	
	@ManyToOne (targetEntity = com.ochnas.volunteersignup.domain.User.class)
	@JoinColumn(name = "USER_ID", nullable = false) 
	private User coordinator;
	
	@Temporal(TemporalType.DATE)
	@Column(name = "START_DATE", nullable = false)
	private Date startDate;
	@Temporal(TemporalType.DATE)
	@Column(name = "END_DATE", nullable = false)
	private Date endDate;	
	@Embedded
	@AttributeOverrides({
		@AttributeOverride(name = "hourOfDay",
				           column = @Column(name = "START_TIME_HOUR_OF_DAY")),
		@AttributeOverride(name = "minutes",
						           column = @Column(name = "START_TIME_MINUTES"))				            
	})
	private Time startTime;
	@Embedded
	@AttributeOverrides({
		@AttributeOverride(name = "hourOfDay",
				           column = @Column(name = "END_TIME_HOUR_OF_DAY")),
		@AttributeOverride(name = "minutes",
						           column = @Column(name = "END_TIME_MINUTES"))				            
	})
	private Time endTime;
	
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "event")
    private List<Position> positions = new ArrayList<Position>();
	
	public Event() {
		super();
	}
	
	
	public Event(String name, String description, User coordinator, Date startDate, Date endDate, Time startTime, Time endTime) {
		super();
		this.name = name;
		this.description = description;
		this.coordinator = coordinator;
		this.startDate = startDate;
		this.endDate = endDate;
		this.startTime = startTime;
		this.endTime = endTime;
	}
	
	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
	public User getCoordinator() {
		return coordinator;
	}
	public void setCoordinator(User coordinator) {
		this.coordinator = coordinator;
	}
	public Date getStartDate() {
		return startDate;
	}
	public void setStartDate(Date startDate) {
		this.startDate = startDate;
	}
	public Date getEndDate() {
		return endDate;
	}
	public void setEndDate(Date endDate) {
		this.endDate = endDate;
	}
	public Time getStartTime() {
		return startTime;
	}
	public void setStartTime(Time startTime) {
		this.startTime = startTime;
	}
	public Time getEndTime() {
		return endTime;
	}
	public void setEndTime(Time endTime) {
		this.endTime = endTime;
	}
	
	/**
	 * Method to add position
	 * @param p - Position
	 */	
	public Position addPosition(Position p) {
		p.setEvent(this);
		positions.add(p);
		return p;
	}
	
	/**
	 * Method to remove a position from the list of positions.
	 * @param position - Position
	 * @return boolean - true, if removal is successful; false, otherwise.
	 */
	public boolean removePosition(Position position) {
		return positions.remove(position);
	}
	
	/**
	 * Method to return list of positions.
	 * @return Set<Position>
	 */
	public List<Position> getPositions() {
		Position[] posArray = positions.toArray(new Position[0]);
		Arrays.sort(posArray, sortByAscendingName);
		return Collections.unmodifiableList(Arrays.asList(posArray));
	}

	@Override
	public String toString() {
		
		StringBuffer strBuff = new StringBuffer("Event[id=");
		strBuff.append(id);
		strBuff.append("]{name=");
		strBuff.append(name);
		strBuff.append(",description=");
		strBuff.append(description);
		strBuff.append(",coordinator=");
		strBuff.append(coordinator);
		strBuff.append(",startDate=");
		if (null != startDate) {
			strBuff.append(simpleDateFormat.format(startDate));
		} else {
			strBuff.append(startDate);
		}
		strBuff.append(",endDate=");
		if (null != endDate) {
			strBuff.append(simpleDateFormat.format(endDate));
		} else {
			strBuff.append(endDate);
		}
		strBuff.append(",startTime=");
		strBuff.append(startTime);
		strBuff.append(",endTime=");
		strBuff.append(endTime);
		strBuff.append("}");
		return strBuff.toString();
	}


	public void setPositions(List<Position> positions) {
		this.positions = positions;
	}
	
}
